using System;
using Microsoft.Practices.Prism.Events;
using Microsoft.Practices.Prism.ViewModel;
using Microsoft.Practices.Unity;
using Ausy.Silverlight.Survey.Infrastructure.Common;
using Ausy.Silverlight.Survey.Infrastructure.Events;
using System.Windows.Threading;

namespace Ausy.Silverlight.Survey.QuestionModule.ViewParts
{
    /// <summary>
    /// Cette classe représente le Vue Model pour le Timer
    /// </summary>
    public class TimerViewModel : ViewModel<ITimerView>, ITimerViewModel
    {
        #region Private Members

        /// <summary>
        /// Timer pour l'affichage du temps
        /// </summary>
        private DispatcherTimer timer;

        /// <summary>
        /// Counter
        /// </summary>
        private int counter;

        /// <summary>
        /// Date du démarrage du timer
        /// </summary>
        private DateTime StartedDate;

        #endregion
        
        #region ShowTimer Property
        /// <summary>
        /// Property showTimer
        /// </summary>
        private bool showTimer;

        /// <summary>
        /// Property ShowTimer
        /// </summary>
        public bool ShowTimer
        {
            get { return showTimer; }
            set
            {
                if (showTimer != value)
                {
                    showTimer = value;
                    RaisePropertyChanged(() => this.ShowTimer);
                }
            }
        }

        #endregion

        #region Constructor

        /// <summary>
        /// Constructeur par défaut
        /// </summary>
        /// <param name="container">Container Unity pour instanciation des type d'objet</param>
        public TimerViewModel(IUnityContainer container)
            : base(container)
        {

        }

        #endregion

        #region Initialize Method

        /// <summary>
        /// Cette méthode permet l'initialisation du ViewModel avant que le DataContext soit affecté à la vue
        /// </summary>
        protected override void Initialize()
        {
            // Initialisation des données
            this.timer = new DispatcherTimer();
            this.StartedDate = DateTime.Now;
            this.counter = 30;
            this.timer.Interval = new TimeSpan(0, 0, 0,0, 333);
            this.ShowTimer = false;

            timer.Tick +=
                    delegate(object s, EventArgs args)
                    {
                        counter--;
                        if (counter < 1)
                        {
                            this.OnElasped();
                        }
                        else
                        {
                            this.View.TimerState = "State" + counter.ToString();
                        }
                    };

            this.eventAggregator.GetEvent<TimerStartEvent>().Subscribe(this.OnStart);
            this.eventAggregator.GetEvent<TimerStopEvent>().Subscribe(this.OnStop);

            // Initialisation des commandes
        }

        #endregion

        /// <summary>
        /// Cette méthode permet de démarrer le timer
        /// </summary>
        /// <param name="args">arvument de l'event</param>
        public void OnStart(TimerStartEvent args)
        {
            this.ShowTimer = true;
            this.counter = 30;
            this.View.TimerState = "Normal";
            this.StartedDate = DateTime.Now;
            timer.Start();
        }

        /// <summary>
        /// Cette méthode permet d'arreter le timer
        /// </summary>
        /// <param name="args">arvument de l'event</param>
        public void OnStop(TimerStopEvent args)
        {
            if (args.ReturnAction != null)
            {
                timer.Stop();
                var stoppedDate = DateTime.Now;
                var elapsedTime = stoppedDate - this.StartedDate;
                args.ReturnAction(elapsedTime);
            }
        }
        
        /// <summary>
        /// Cette méthode permet de publier un évènement pour indiquer le temps écoulé
        /// </summary>
        /// <param name="args">arvument de l'event</param>
        public void OnElasped()
        {
            this.eventAggregator.GetEvent<TimerElapsedEvent>().Publish(new TimerElapsedEvent());
        }
    }
}
